#!/usr/local/bin/php
<?php
//检查参数
if (count($argv) < 2) {
    echo "Usage:\nphpsuck.php url\n\n";
    exit(-1);
}
$url = $argv[1];

//宽带限制
if ($argc == 3) {
    $max_kb_sec = $argv[2];
} else {
    $max_kb_sec = 1000;
}
//指向xterms的第一列
$term_sol = "\x1b[1G";
$severity_map = array(
    0 => 'info',
    1 => 'warning',
    2 => 'error'
);
$size = 0;
/**
 * 指向流事件的回调函数
 */
function notifier($code, $severity, $msg, $xcode, $sofar, $max)
{
    global $term_sol, $severity_map, $max_kb_sec, $size;
    //当接收到PROGRESS事件时 不打印状态信息前缀
    if ($code != STREAM_NOTIFY_PROGRESS) {
        echo $severity_map[$severity];
    }
    switch ($code) {
        case STREAM_NOTIFY_CONNECT://这个事件当一个连接到资源被建立时触发的 例如当脚本连接到已改http服务器时
            printf("Connected\n");
            $GLOBALS['begin_time'] = time() - 0.001;
            break;
        case STREAM_NOTIFY_AUTH_REQUIRED: //当一个认证请求完成 这个事件会通过流的API触发
            printf("Authentiction required: %s\n", trim($msg));
            break;
        case STREAM_NOTIFY_AUTH_RESULT: //一旦认证通过这个事件就触发并告诉你是否是一个成功的认证或者是连接失败
            printf("Logged in: %s\n", trim($msg));
            break;
        case STREAM_NOTIFY_MIME_TYPE_IS://HTTP流处理层(http://和https://) 在请求的响应中获得Content-Type信息时触发该事件
            printf("Mime type: %s\n", trim($msg));
            break;
        case STREAM_NOTIFY_FILE_SIZE_IS://当FTP处理层计算出文件的大小的时候触发该事件.或者当一个HTTP处理层看到Content-length头信息时触发
            printf("Downloading  %d Kb\n", $max / 1024);
            //设置全局变量
            $size = $max;
            break;
        case STREAM_NOTIFY_REDIRECTED://这个事件是通过HTTP处理层在它遇到一个重定向请求(Location:header)时触发
            printf("Redirecting to: %s\n", trim($msg));
            break;
        case STREAM_NOTIFY_PROGRESS://它是在数据包到达后迅速发送的 可以用这个事件执行带宽的限制并显示进度条
            //计算星星标记和条纹的个数
            if ($size) {
                $stars = str_repeat('*', $c = $sofar * 50 / $size);
            } else {
                $stars = '';
            }
            $stripe = str_repeat('-', 50 - strlen($stars));

            //用kb/sec的单位计算下载速度
            $Kb_sec = ($sofar / (time() - $GLOBALS['begin_time'])) / 1024;
            //如果超过最高的输出速度 暂停脚本
            while ($Kb_sec > $max_kb_sec) {
                usleep(1);
                $Kb_sec = ($sofar / (time() - $GLOBALS['begin_time'])) / 1024;
            }
            //显示进度条
            printf("{$term_sol} [%s] %d kb %.1f kb/sec", $stars . $stripe, $sofar / 1024, $Kb_sec);
            break;
        case STREAM_NOTIFY_FAILURE://出错的时候触发
            printf("Failure: %s\n", $msg);
            break;
    }

}

//同时确定保存的文件名
$url_data = parse_url($argv[1]);

$file = basename($url_data['path']);

if (empty($file)) {
    $file = 'fool.gz';
}

printf("Saving to $file\n");

//$fil = "compress:zlib://id3-0.2.gz";
$fil = "compress.zlib://fool.gz";

//创建上下文并且设置notifier 的回调函数
$context = stream_context_create();
stream_context_set_params($context, array('notification' => 'notifier'));
//$url = 'http://pecl.php.net/get/id3-0.2.tgz';
$fp = fopen($url, 'rb', false, $context);
if (is_resource($fp)) {
    //打开本地文件
    $fs = fopen($fil, 'wb9', false, $context) or die('打开本地文件失败');
    while (!feof($fp)) {
        //以每块1024字节来读取数据
        $data = fgets($fp, 1024);
        fwrite($fs, $data);
    }
    fclose($fs);
}
fclose($fp);
printf("{$term_sol}[%s] Download time: %sd\n", str_repeat('*', 50), time() - $GLOBALS['begin_time']);

//执行
//php url_stream2.php http://pecl.php.net/get/id3-0.2.tgz
//压缩流协议有问题 没搞明白 咋回事